package com.atguigu.tingshu.album.config;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;

@Configuration
public class BloomFilterConfig {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private ExecutorService executorService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Bean
    public RBloomFilter bloomFilter() throws InterruptedException {
        // 如果布隆过滤器已经存在则什么都不做
        if (this.redisTemplate.hasKey(RedisConstant.ALBUM_BLOOM_FILTER)){
            return null;
        }
        RBloomFilter<String> bloomFilter = this.redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        // 专辑：50w 声音：5Y 分类：几百条
        bloomFilter.tryInit(100000000, 0.03);

        // 初始化专辑：
        Long count = this.albumInfoMapper.selectCount(null);
        Integer pageSize = 1000;
        Integer pageNum = (int)(count / pageSize);
        pageNum = count % pageSize == 0 ? pageNum : pageNum + 1;
        // 使用倒计数器CountDownlatch
        CountDownLatch latch1 = new CountDownLatch(pageNum);
        for (long i = 0; i < pageNum; i++) {
            long finalI = i;
            executorService.execute(() -> {
                Page<AlbumInfo> albumInfoPage = this.albumInfoMapper.selectPage(new Page<>(finalI + 1, pageSize), null);
                List<AlbumInfo> records = albumInfoPage.getRecords();
                // 把这一页的数据放入布隆过滤器
                records.forEach(albumInfo -> {
                    // 以缓存的key作为数据放入布隆过滤器
                    bloomFilter.add(RedisConstant.ALBUM_INFO_PREFIX + albumInfo.getId());
                });
                latch1.countDown();
            });
        }

        // TODO：声音数据

        // TODO: 分类

        latch1.await();
        return bloomFilter;
    }
}
